<template>
	<ul :class="classes" :style="styles">
		<slot></slot>
	</ul>
</template>

<script lang="ts">
	import Anes from "../base";
	import { Prop, Watch, Component } from "vue-property-decorator";
	import {
		oneOf,
		findComponentsDownward,
		findComponentsUpward
	} from "../../utils/assist";
	import Submenu from "./submenu.vue";
	@Component
	export default class Menu extends Anes {
		@Prop({
			type: String,
			default: "vertical",
			validator(value) {
				return oneOf(value, ["horizontal", "vertical"]);
			}
		})
		mode!: string;
		@Prop({
			type: String,
			default: "light",
			validator(value) {
				return oneOf(value, ["light", "dark", "primary"]);
			}
		})
		theme!: string;
		@Prop([String, Number]) activeName!: string | number;
		@Prop({
			type: Array,
			default() {
				return [];
			}
		})
		openNames!: Array<string | number>;
		/*是否开启手风琴模式，开启后每次至多展开一个子菜单*/
		@Prop({ type: Boolean, default: false }) accordion!: boolean;
		@Prop({ type: String, default: "240px" }) width!: string;
		prefixCls = "ivu-menu";
		currentActiveName = this.activeName;
		openedNames: Array<string | number> = [];

		mounted() {
			this.openedNames = [...this.openNames];
			this.updateOpened();
			this.$nextTick(() => this.updateActiveName());
			this.$on("on-menu-item-select", (name: string | number) => {
				this.currentActiveName = name;
				this.$emit("on-select", name);
			});
		}

		get classes() {
			let theme = this.theme;
			if (this.mode === "vertical" && this.theme === "primary") theme = "light";

			return [
				`${this.prefixCls}`,
				`${this.prefixCls}-${theme}`,
				{
					[`${this.prefixCls}-${this.mode}`]: this.mode
				}
			];
		}
		get styles() {
			if (this.mode === "vertical") return { width: this.width };
			return {};
		}

		updateActiveName() {
			if (this.currentActiveName === undefined) {
				this.currentActiveName = -1;
			}
			this.broadcast("Submenu", "on-update-active-name", [false]);
			this.broadcast("MenuItem", "on-update-active-name", [
				this.currentActiveName
			]);
		}
		updateOpenKeys(name: string | number) {
			const names = [...this.openedNames];
			const index = names.indexOf(name);
			if (this.accordion)
				findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
					item.opened = false;
				});
			if (index >= 0) {
				let currentSubmenu = null;
				findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
					if (item.name === name) {
						currentSubmenu = item;
						item.opened = false;
					}
				});
				findComponentsUpward<Submenu>(currentSubmenu, "Submenu").forEach(item => {
					item.opened = true;
				});
				findComponentsDownward<Submenu>(currentSubmenu, "Submenu").forEach(
					item => {
						item.opened = false;
					}
				);
			} else {
				if (this.accordion) {
					let currentSubmenu = null;
					findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
						if (item.name === name) {
							currentSubmenu = item;
							item.opened = true;
						}
					});
					findComponentsUpward<Submenu>(currentSubmenu, "Submenu").forEach(
						item => {
							item.opened = true;
						}
					);
				} else {
					findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
						if (item.name === name) item.opened = true;
					});
				}
			}
			const openedNames = findComponentsDownward<Submenu>(this, "Submenu")
				.filter(item => item.opened)
				.map(item => item.name);
			this.openedNames = [...openedNames];
			this.$emit("on-open-change", openedNames);
		}
		updateOpened() {
			findComponentsDownward<Submenu>(this, "Submenu").forEach(item => {
				if (this.openedNames.indexOf(item.name) > -1) item.opened = true;
				else item.opened = false;
			});
		}
		handleEmitSelectEvent(name: string | number) {
			this.$emit("on-select", name);
		}
		/* 		@Emit("")
				onSelect(name: string | number); */

		@Watch("openNames")
		onOpenNames(names: Array<string | number>) {
			this.openedNames = names;
		}
		@Watch("activeName")
		OnActiveName(val: string | number) {
			this.currentActiveName = val;
		}
		@Watch("currentActiveName")
		onCurrentActiveName() {
			this.updateActiveName();
		}
	}
</script>

<style>
</style>